perm filename KLEIN.SAI[GEO,BGB] blob sn#001307 filedate 1972-10-28 generic text, type T, neo UTF8
00100	ENTRY DUMMY;
00200	BEGIN	"KLEIN"
00300		REQUIRE "ABBREV" SOURCE_FILE;
00400	α ...after Felix Klein, 1849-1925, German Mathematician;
00500		EXTERNAL STRING ARRAY  NAME[1:50];
00600		REQUIRE "GEOMES" SOURCE_FILE;
00700	
00800		DEFINE THRICE="FOR I←1 STEP 1 UNTIL 3 DO";
00900	
01000	
01100	INTERNAL ISUBR PYRAMID (ITG F);
01200	BEGIN	"PYRAMID"
01300		INTEGER V,V0,E,E0,E1,E2,V1,V2,PEAK,EX;
01400		REAL X,Y,Z; INTEGER I;
01500	
01600	α VERTEX ARGUMENT - GIVEN THE PEAK FORM THE BASE;
01700	IF VTYPE(F) THEN
01800	BEGIN
01900		V ← F; E0←E2←PED(V); V2←OTHER(E2,V);
02000		DO ⊂ E1←E2;V1←V2; E2←ECCW(E1,V);V2←OTHER(E2,V);
02100		     F←FCCW(E1,V); IF ¬LINKED(V1,V2) THEN EX←MKFE(V1,F,V2);
02200		⊃ UNTIL E2=E0; RETURN(V);
02300	END;
02400	
02500	α FACE ARGUMENT - GIVEN THE BASE FORM THE PEAK;
02600		X←Y←Z←I←0;
02700		E←E0←PED(F);
02800		V0 ← VCW(E0,F);
02900		PEAK ← MKEV(F,V0);
03000		WHILE TRUE DO 
03100	BEGIN
03200		V ← VCCW(E,F);
03300		X←X+XWC(V); Y←Y+YWC(V); Z←Z+ZWC(V);
03400		INCREM(I);
03500		IF V=V0 THEN DONE;
03600		E ← ECCW(E,F);
03700		EX ← MKFE(PEAK,F,V);
03800	END;
03900		DACR(X/I,PEAK-3);
04000		DACR(Y/I,PEAK-2);
04100		DACR(Z/I,PEAK-1);
04200		RETURN(PEAK);
04300	END	"PYRAMID";
     

00100	INTERNAL BOOLEAN SUBR CONVEX (ITG F);
00200	BEGIN "CONVEX"
00300		ITG V1,V,V2,E,E0,I,FLG;
00400		REAL A,B,C,X1,Y1,X2,Y2,X,Y,P,Q;
00500		XSUBR FACOEF(ITG F,FLG);
00600		FACOEF(F,0);FLG←FALSE;
00700	α SELECT LARGEST FACE COEFFICIENT;
00800		I ← (IF ABS(AA(F))>ABS(BB(F)) THEN
00900		    (IF ABS(AA(F))>ABS(CC(F)) THEN 0 ELSE 2) ELSE
01000		    (IF ABS(BB(F))>ABS(CC(F)) THEN 1 ELSE 2));
01100	
01200		E0←E←PED(F); V1←0; V←VCW(E,F); V2←VCCW(E,F);
01210		X ← CASE I OF ( YWC(V),ZWC(V),XWC(V) );
01212		Y ← CASE I OF ( ZWC(V),XWC(V),YWC(V) );
01220		X2 ← CASE I OF ( YWC(V2),ZWC(V2),XWC(V2) );
01222		Y2 ← CASE I OF ( ZWC(V2),XWC(V2),YWC(V2) );
01300	
01400	α A POLYGON IS CONVEX IF ALL ITS INTERIOR ANGLES ARE LESS THAN π;
01500	DO BEGIN
01600		V1 ← V; V ← V2; V2 ← VCCW(E,F); E ← ECCW(E,F);
01700		X1 ← X; X ← X2; X2 ← CASE I OF ( YWC(V2),ZWC(V2),XWC(V2) );
01800		Y1 ← Y; Y ← Y2; Y2 ← CASE I OF ( ZWC(V2),XWC(V2),YWC(V2) );
01900		A ← Y1-Y; B ← X-X1; C ← X1*Y - X*Y1;
02000		P←Q;Q←A*X2+B*Y2+C;
02050		IF  FLG∧(P⊗Q)<0 THEN RETURN(FALSE) ELSE FLG←TRUE;
02100	END UNTIL E=E0;
02200		RETURN(TRUE);
02300	END "CONVEX";
     

00100	INTERNAL ISUBR MKCONVEX (ITG Q);
00200	BEGIN "MKCONVEX"
00300		ITG B,F;
00400		IF FTYPE(Q)∧CONVEX(Q) THEN OUTSTR("	CONVEX"&↓)
00500		ELSE OUTSTR("	CONCAVE"&↓);
00600	END;
     

00100	INTERNAL ISUBR KILLF (ITG F);
00200	BEGIN "KILLF"
00300		ITG A,E,V,V0,N; REAL X,Y,Z;
00400		
00500		E←PED(F); V0←VCW(E,F); V←VCCW(E,F); A←ECCW(E,F);
00600		F←KLFE(E);
00700	
00800		X←XWC(V); Y←YWC(V); Z←ZWC(V); N←1;
00900		DO BEGIN
01000			E←A;A←ECCW(A,F);
01100			IF PVT(E)=V THEN INVERT(E);V←KLVE(E);
01200			X ← X+XWC(V); Y ← Y+YWC(V); Z ← Z+ZWC(V); INCREM(N);
01300		END UNTIL V=V0;
01400	
01500	α PLACE VERTEX AT CENTER OF THE DECEASED FACE;
01600		XWC(V0)←X/N;	YWC(V0)←Y/N;	ZWC(V0)←Z/N;
01700		RETURN(V0);
01800	END "KILLF";
     

00100	INTERNAL ISUBR SWEEP (ITG F,META,CTRL);
00200	BEGIN	"SWEEP"
00300		INTEGER I,NN,NCOUNT;
00400		INTEGER V0,V1,V2,Q;
00500		INTEGER U0,U1,U2,E,E0,F0,CELL,EVV,EUV;
00600	
00700		IF VTYPE(F) THEN RETURN(PYRAMID(F));
00800		IF ¬FTYPE(F) THEN RETURN(F);
00900		NN←NCOUNT←NCNT(F);
01000		NN ← 0 MAX NN;
01100		F0←F; E0 ← E ← PED(F);
01200	
01300	α HANDLE POSSIBLE WIRE SWEEP CASE;
01400		IF E=PCW(E) THEN
01500	BEGIN	"WIRE SWEEP"
01600		FOR I←2 TO ABS(NCOUNT) DO E←NCW(E);
01700		V1←NVT(E); V2←MKEV(F,V1);
01800		WHILE TRUE DO
01900		BEGIN "COPY'N'CDR"
02000			V1←PVT(E); V2←MKEV(F,V2);
02100			DAC(LAC(V1-3),V2-3);
02200			DAC(LAC(V1-2),V2-2);
02300			DAC(LAC(V1-1),V2-1);
02400			IF E=PCW(E) THEN DONE ELSE E←PCW(E);
02500		END "COPY'N'CDR";
02600		E ← MKFE(V1,F,V2);
02700		F ← NFACE(E);
02800		FOR I←1 TO (ABS(NCOUNT)-1) DO
02900		BEGIN "CDR'N'JOIN"
03000			Q←ECCW(E,F); V1 ← OTHER(Q,V1);
03100			Q← ECW(E,F); V2 ← OTHER(Q,V2);
03200			E ← MKFE(V2,F,V1);
03300		END "CDR'N'JOIN";
03400		Q←PED(F0); Q←ECCW(Q,F0); PED.(Q,F0);
03500		NCNT.(NCOUNT,F0);
03600		RETURN(F0);
03700	END "WIRE SWEEP";
03800	
03900		IF META∧¬CTRL THEN ⊂ F ← PYRAMID(F);RETURN(F);⊃;
     

00100	α THE NN & NCOUNT ARE FOR LAMINA PARTIAL FACE SWEEPING;
00200		IF NN≠0 THEN E←ECCW(E,F)ELSE NN←ABS(NCOUNT);
00300	
00400	α MAKE PED SPOKE;
00500		U1 ← U0 ← VCW(E,F);
00600		V1 ← V0 ← MKEV(F,U0);
00700	
00800	α MAKE CELLS;
00900	DO BEGIN "CELLS"
01000		U2 ← VCCW(E,F);
01100		E  ← ECCW(E,F);
01200		V2 ← (IF U2=U0 THEN V0 ELSE MKEV(F,U2));
01300		EVV ← MKFE(V1,F,V2);
01400		IF NCOUNT ∧ ABS(NCOUNT)=NN THEN E0←EVV;
01500		CELL ← NFACE(EVV);
01600		NCNT.(4,CELL);
01700	α ANTI-PRISM CELLS ARE TRIANGULAR;
01800		IF CTRL THEN
01900		EUV ← 	(IF META THEN MKFE(U1,CELL,V2)
02000			         ELSE MKFE(V1,CELL,U2));
02100		U1←U2; V1←V2; NN←NN-1;
02200	END	"CELLS"	UNTIL U2=U0 ∨ NN=0;
02300	
02400		IF NCOUNT THEN 
02500		⊂ PED.(E0,F); NCNT.(NCOUNT,F0) ⊃;
02600		RETURN(F);
02700	END	"SWEEP";
02800	
02900	INTERNAL ISUBR PRISM (ITG F); RETURN(SWEEP(F,0,0));
03000	INTERNAL ISUBR CWPRISMIOD (ITG F); RETURN(SWEEP(F,1,1));
03100	INTERNAL ISUBR CCWPRISMIOD (ITG F); RETURN(SWEEP(F,0,1));
     

00100	α COMPLETE A SOLID OF ROTATION FROM A NON-ZERO NCOUNT SWEEPING FACE;
00200	INTERNAL PROCEDURE ROTCOM (ITG F);
00300	BEGIN	"ROTCOM"
00400		INTEGER NCOUNT;
00500	α BLESS THE ARGUMENTS;
00600		IF ¬FTYPE(F) THEN RETURN;
00700		NCOUNT ← NCNT(F); IF NCOUNT≥0 THEN RETURN;
00800		NCOUNT ← ABS(NCOUNT); NCNT.(NCOUNT,F);
00900	BEGIN
01000		INTEGER ARRAY PAIRS[-1:NCOUNT,1:2];
01100		INTEGER I,MTOTAL,SKPCNT,NN;
01200		INTEGER E,V,E0;
01300		INTEGER NNCNT;NNCNT←NCOUNT;NCOUNT←0;
01400	
01500	α SETUP THE PERIMETER COUNTS;
01600		NN ← NNCNT;
01700		E←E0←PED(F);
01800		MTOTAL←0; DO ⊂ E←ECCW(E,F);INCREM(MTOTAL) ⊃ UNTIL E=E0;
01900		SKPCNT	←	(MTOTAL - 2*NNCNT)%2 - 1;
02000	
02100	α CDR NNCNT+1 VERTICES DOWN THE PERIMETER;
02200		E ← E0;
02300		FOR I←0 STEP 1 UNTIL NNCNT DO
02400		⊂ PAIRS[I,1]←VCW(E,F); E←ECCW(E,F) ⊃;
02500	
02600	α SKIP AROUND A POLE CAP;
02700		FOR I←1 STEP 1 UNTIL SKPCNT DO E←ECCW(E,F);
02800	α CDR NNCNT+1 VERTICES UP THE PERIMETER;
02900		FOR I←NNCNT STEP -1 UNTIL 0 DO
03000		⊂ PAIRS[I,2]←VCW(E,F); E←ECCW(E,F) ⊃;
03100	α CALL JOINVV FOREACH PAIR;
03200		FOR I←0 STEP 1 UNTIL NN DO 
03300		E←MKFE(PAIRS[I,2],F,PAIRS[I,1]);
03400	END;
03500		RETURN;
03600	END	"ROTCOM";
     

00100	INTERNAL ITG PROCEDURE GLUE (ITG F1,F2);
00200	BEGIN	"GLUE"
00300	
00400		ITG B,B1,B2,F,E,V,E0;
00500		ITG V1,V2,E1,E2,F3;
00600		ITG CCW,CW,OF1,OF2;
00700		REAL X,Y,Z;
00800		INTEGER I,J,N;
00900		BOOLEAN BBFLG;
01000	
01100	α GET TWO FACES OFF THE PDL;
01200		BBFLG	←	FALSE;
01300		IF (¬FTYPE(F1) ∨ ¬FTYPE(F2))
01400		 ∧ BTYPE(F1) ∧ BTYPE(F2) THEN
01500	BEGIN
01600		B1	←	F1;
01700		B2	←	F2;
01800		BBFLG	←	TRUE;
01900	END ELSE ⊂ B1 ← BODY(F1); B2 ← BODY(F2);⊃;
02000	
02100	α BODY FUSION WHEN NECESSARY, B2 BECOMES B1;
02200		IF B1≠B2 THEN
02300		BEGIN
02400			ITG Q;
02500			F←NFACE(B1);
02600			Q←PFACE(B2);PFACE.(Q,F);Q←PFACE(B);NFACE.(F,Q);
02700			Q←NFACE(B2);PFACE.(Q,B1);Q←NFACE(B2);NFACE.(B1,Q);
02800	
02900			E←NED(B1);
03000			Q←PED(B2);PED.(Q,E);Q←PED(B);NED.(E,Q);
03100			Q←NED(B2);PED.(Q,B1);Q←NED(B2);NED.(B1,Q);
03200	
03300			V←NVT(B1);
03400			Q←PVT(B2);PVT.(Q,V);Q←PVT(B);NVT.(V,Q);
03500			Q←NVT(B2);PVT.(Q,B1);Q←NVT(B2);NVT.(B1,Q);
03600	
03700			KLB(B2);
03800		END;
03900	
04000		IF BBFLG THEN RETURN(B1);
04100		B ← B1;
     

00100		N ← NCNT(F1);
00200	α	IF N≠NCNT(F2) THEN RETURN(F1);
00300	
00400	BEGIN	"FGLUE"
00500		SAFE ITG ARRAY EARRY1,EARRY2,VARRY1,VARRY2[1:N];
00600	α PICK 'EM UP;
00700		E1←PED(F1);
00800		E2←PED(F2);
00900		FOR I←1 TO N DO
01000	BEGIN
01100		VARRY1[I] ← VCCW(E1,F1);
01200		EARRY1[I] ← E1;
01300		VARRY2[I] ← VCW(E2,F2);
01400		EARRY2[I] ← E2;
01500		E1 ← ECCW(E1,F1);
01600		E2 ←  ECW(E2,F2);
01700	END;
01800	
01900	α REPLACE V2 OCCURENCES WITH V1'S;
02000		FOR I←1 TO N DO
02100	BEGIN "VREPLACE"
02200		V1 ← VARRY1[I];
02300		V2 ← VARRY2[I];
02400		E←E0←PED(V2);
02500	DO BEGIN
02600		IF PVT(E)=V2 THEN PVT.(V1,E) ELSE NVT.(V1,E);
02700		E←ECCW(E,V1);
02800	END UNTIL E=E0;
02900	END "VREPLACE";
     

00100	α REPLACE F1 OCCURENCES WITH THE OTHER OF F2;
00200	α ...AND DO WING REPLACEMENTS;
00300		FOR I←1 TO N DO
00400	BEGIN
00500		E1 ← EARRY1[I];
00600		E2 ← EARRY2[I];
00700		OF1 ← OTHER(E1,F1);
00800		OF2 ← OTHER(E2,F2);
00900		CCW ← ECCW(E2,OF2);
01000		 CW ←  ECW(E2,OF2);
01100		OTHER.(OF2,E1,OF1);
01200		WING(CCW,E1);
01300		WING(CW,E1);
01400		IF PED(OF2)=E2 THEN PED.(E1,OF2);
01500	END;
01600	
01700		KLF(B,F1);
01800		KLF(B,F2);
01900		FOR I←1 TO N DO 
02000		⊂ KLE(B,EARRY2[I]);KLV(B,VARRY2[I]) ⊃;
02100	END	"FGLUE";
02200		RETURN(B);
02300	END	"GLUE";
02400	
     

00100	INTERNAL SUBR FVDUAL (ITG B);
00200	BEGIN	"FVDUAL"
00300		ITG Q1,Q2,F,E,V,E0,I;
00400		REAL X,Y,Z;
00500	
00600		IF ¬BTYPE(B) THEN RETURN;
00700	
00800	
00900	α COMPUTE CENTER LOCUS OF ALL THE FACES;
01000		F←PFACE(B);
01100		WHILE FTYPE(F) DO
01200	BEGIN
01300		X←Y←Z←0;I←0;
01400		E0←E←PED(F);
01500		DO BEGIN
01600			V ← VCCW(E,F);	E ← ECCW(E,F);
01700			X ← X + XWC(V);	Y ← Y + YWC(V);	Z ← Z + ZWC(V);
01800			I ← I + 1;
01900		END UNTIL E0=E;
02000		X←X/I;Y←Y/I;Z←Z/I;
02100		DACR(X,F-3);DACR(Y,F-2);DACR(Z,F-1);
02200		DAC(LAC(F+1),F+3); DIP(8,F);
02300		F ← PFACE(F);
02400	END;
02500	
02600		V←PVT(B);
02700		WHILE VTYPE(V) DO ⊂ DAC(LAC(V+3),V+1);DIP(2,V);V ← PVT(V);⊃;
02800		E←PED(B);
02900		WHILE ETYPE(E) DO
03000	BEGIN
03100		Q1 ← LAC(E+1);	Q2 ← LAC(E+3);
03200		DAC(Q1,E+3);	DAC(Q2,E+1);
03300		START_CODE MOVE 1,E;MOVSS 5(1);END;
03400		E ← PED(E);
03500	END;
03600		Q1 ← LAC(B+1);	Q2 ← LAC(B+3);
03700		DAC(Q1,B+3);	DAC(Q2,B+1);
03800	END "FVDUAL";
03900	END;
04000	KLEIN.SAI - EOF.